package com.lc.ibps.platform.rest.system;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.jodconverter.OfficeDocumentConverter;
import org.jodconverter.office.DefaultOfficeManagerBuilder;
import org.jodconverter.office.OfficeException;
import org.jodconverter.office.OfficeManager;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.lc.ibps.api.base.query.QueryFilter;
import com.lc.ibps.api.base.query.QueryOP;
import com.lc.ibps.base.core.util.AppUtil;
import com.lc.ibps.base.core.util.ArrayUtil;
import com.lc.ibps.base.core.util.BeanUtils;
import com.lc.ibps.base.core.util.FileUtil;
import com.lc.ibps.base.core.util.JacksonUtil;
import com.lc.ibps.base.core.util.string.StringUtil;
import com.lc.ibps.base.framework.page.PageResult;
import com.lc.ibps.base.web.context.ContextUtil;
import com.lc.ibps.base.web.util.AppFileUtil;
import com.lc.ibps.cloud.entity.APIRequest;
import com.lc.ibps.cloud.entity.APIResult;
import com.lc.ibps.common.file.persistence.entity.AttachmentPo;
import com.lc.ibps.common.file.service.AttachmentService;
import com.lc.ibps.components.upload.UploadStrategySelector;
import com.lc.ibps.components.upload.model.FileInfo;
import com.lc.ibps.components.upload.service.IFileInfoPersistenceService;
import com.lc.ibps.components.upload.service.IUploadService;
import com.lc.ibps.components.upload.util.FileInfoPersistenceFactory;
import com.lc.ibps.components.upload.util.UploadUtil;
import com.lc.ibps.web.controller.BaseApiController;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;

@RequestMapping(value = "/api/webapi/attachmentService")
@Api(value = "/attachmentService", tags = "系统管理-附件信息服务")
@RestController
public class AttachmentController extends BaseApiController {

	private AttachmentService attachmentService;
	
	private UploadStrategySelector uploadStrategySelector;
	
	private IUploadService uploadService;

	public AttachmentController() {
		attachmentService = AppUtil.getBean(AttachmentService.class);
		uploadStrategySelector = AppUtil.getBean(UploadStrategySelector.class);
	}
	
	
	public IUploadService getUploadService() throws Exception {
		return getUploadService(FileInfoPersistenceFactory.getIUploadResultPersistence());
	}
	public IUploadService getUploadService(String beanId) throws Exception {
		if (uploadService == null) {
			uploadService = uploadStrategySelector.getIUploadService();
			uploadService.setFileInfoPersistenceService(FileInfoPersistenceFactory.getIUploadResultPersistence(beanId));
		}
		return uploadService;
	}
	

	public IUploadService getUploadService(IFileInfoPersistenceService fileInfoPersistenceService) throws Exception {
		if (uploadService == null) {
			uploadService = uploadStrategySelector.getIUploadService();
			uploadService.setFileInfoPersistenceService(fileInfoPersistenceService);
		}
		return uploadService;
	}


	@ApiOperation(value = "获取附件信息", notes = "获取附件信息 type：id/path")
	@RequestMapping(value = "/getInfo", method = RequestMethod.GET)
	public APIResult<Map<String, Object>> getInfo(
			@ApiParam(name = "id", value = "值", required = true) @RequestParam(name = "id", required = true) String id,
			@ApiParam(name = "type", value = "值类型", required = true) @RequestParam(name = "type", required = true) String type) {
		APIResult<Map<String, Object>> result = new APIResult<>();
		AttachmentPo attachment = null;
		String data = null;
		try {
			if (StringUtil.isNotEmpty(id)) {
				if (type.equals("path")) {
					data = attachmentService.getAttachmentByPathJson(id);
				} else {
					data = attachmentService.getAttachmentJson(id);
				}
			}
			attachment = JacksonUtil.getDTO(data, AttachmentPo.class);
			Map<String, Object> map = new HashMap<String, Object>();
			map.put("id", attachment.getId());
			map.put("fileName", attachment.getFileName());
			map.put("filePath", attachment.getFilePath());
			map.put("totalBytes", attachment.getTotalBytes());
			map.put("ext", attachment.getExt());
			result.setData(map);
			result.setMessage("获取附件信息成功！");
		} catch (Exception e) {
			if (e instanceof RuntimeException) {
				result = getExceptionResult(result, WARN, "获取附件信息失败！", e);
			} else {
				result = getExceptionResult(result, ERROR, "获取附件信息失败！", e);
			}
		}
		return result;
	}

	@ApiOperation(value = "获取附件信息", notes = "根据用户查询附件信息列表")
	@RequestMapping(value = "/listJsonByUser", method = RequestMethod.POST)
	public APIResult<List<AttachmentPo>> listJsonByUser(
			@ApiParam(name = "request", value = "传入查询请求json字符串", required = true) @RequestBody(required = true) APIRequest request) {
		APIResult<List<AttachmentPo>> result = new APIResult<>();
		try {
			QueryFilter queryFilter = getQuerFilter(request);
			queryFilter.addFilter("CREATOR_", ContextUtil.getCurrentUserId(), QueryOP.EQUAL);
			String listData = attachmentService.query(queryFilter);
			if (JacksonUtil.isJsonObject(listData)) {
				List<AttachmentPo> list = JacksonUtil.getDTOList(JacksonUtil.getString(listData, "data"),
						AttachmentPo.class);
				PageResult pageResult = PageResult.fromJson(JacksonUtil.getString(listData, "pageResult"));
				result.setData(list);
				result.addVariable("pageResult", pageResult);
			}
			result.setMessage("获取附件列表成功！");
		} catch (Exception e) {
			result = getExceptionResult(result, ERROR, "获取附件列表失败！", e);
		}
		return result;
	}
	
	
	@ApiOperation(value = "获取附件信息", notes = "获取附件信息")
	@RequestMapping(value = "/getImage", method = RequestMethod.GET)
	public void getImage(
			@ApiParam(name = "id", value = "值", required = true) @RequestParam(name = "id", required = true) String id) throws Exception {
		OutputStream out = null;	
		InputStream is = null;
		try {
			this.getUploadService();
			FileInfo fileInfo = uploadService.downloadFile(id);
			 is = new ByteArrayInputStream( fileInfo.getFileBytes()); 
			response.setContentType("image/png");
			out = response.getOutputStream();
			byte[] bs = new byte[1024];
			int n = 0;
			while ((n = is.read(bs)) != -1) {
				out.write(bs, 0, n);
			}
			out.flush();
			} catch (Exception ex) {
				ex.printStackTrace();
			} finally {
				if (is != null)
					is.close();
				if (out != null)
					out.close();
			}
	
	}
	
	@ApiOperation(value = "获取附件信息", notes = "获取附件信息")
	@RequestMapping(value = "/getFile", method = RequestMethod.GET)
	public void getFile(
			@ApiParam(name = "id", value = "值", required = true) 
			@RequestParam(name = "id", required = true) String id,
			@ApiParam(name = "type", value = "类型", required = true) 
			@RequestParam(name = "type", required = true) String type,
			@ApiParam(name = "ext", value = "扩展名", required = false)
			@RequestParam(name = "ext", required = true) String ext) throws Exception {
		OutputStream out = null;	
		InputStream is = null;
		String[] office = { "doc", "docx", "ppt", "pptx", "xls", "xlsx"};
		try {
			this.getUploadService();
			FileInfo fileInfo = uploadService.downloadFile(id);
			is = new ByteArrayInputStream( fileInfo.getFileBytes()); 
			if("pdf".equalsIgnoreCase(type) || ArrayUtil.contains(office, ext)){
				response.setContentType("application/pdf");
			}else if("image".equalsIgnoreCase(type)){
				response.setContentType("image/png");
			}else if("video".equals(type)){ 
				response.setContentType("video/"+ext);
			}
			
			if (ArrayUtil.contains(office, ext)) {
				String path = this.getOfficOutputDir();
				String filePath = UploadUtil.mergeAbsolutePath(path, new String[] { "openOffice" });
				String destFile = filePath + File.separator + id + ".pdf";
				String sourceFile = filePath + File.separator + id + "." + ext;
				if (!FileUtil.isExistFile(sourceFile)) {
					FileUtil.createFolderFile(sourceFile);
					FileUtil.writeByte(sourceFile, fileInfo.getFileBytes());
				}
				if (!FileUtil.isExistFile(destFile)) {
					office2PDF(sourceFile, destFile);
				}
				byte[] readByte = FileUtil.readByte(destFile);
				is = new ByteArrayInputStream(readByte); 
			}
			out = response.getOutputStream();
			byte[] bs = new byte[1024];
			int n = 0;
			while ((n = is.read(bs)) != -1) {
				out.write(bs, 0, n);
			}
			out.flush();
		} catch (Exception ex) {
			ex.printStackTrace();
		} finally {
			if (is != null)
				is.close();
			if (out != null)
				out.close();
		}
		
	}
	
	private String getOfficOutputDir() {
		String dir = AppUtil.getProperty("office.outputDir");
		if (BeanUtils.isEmpty(dir))
			return AppFileUtil.getBasePath();
		return dir;
	}
	
	/**
	 * 将Office文档转换为PDF. 运行该函数需要用到OpenOffice, OpenOffice下载地址为
	 * http://www.openoffice.org/
	 * 
	 * <pre>
	 *  
	 * 方法示例: 
	 * String sourcePath = "F:\\office\\source.doc"; 
	 * String destFile = "F:\\pdf\\dest.pdf"; 
	 * Converter.office2PDF(sourcePath, destFile);
	 * </pre>
	 * 
	 * @param sourceFile
	 *            源文件, 绝对路径. 可以是Office2003-2007全部格式的文档, Office2010的没测试. 包括.doc,
	 *            .docx, .xls, .xlsx, .ppt, .pptx等. 示例: F:\\office\\source.doc
	 * @param destFile
	 *            目标文件. 绝对路径. 示例: F:\\pdf\\dest.pdf
	 * @return 操作成功与否的提示信息. 如果返回 -1, 表示找不到源文件, 或url.properties配置错误; 如果返回 0,
	 *         则表示操作成功; 返回1, 则表示转换失败
	 */
	public static int office2PDF(String sourceFile, String destFile) {
		OfficeManager officeManager = null;
		try {
			File inputFile = new File(sourceFile);

			// 如果目标路径不存在, 则新建该路径
			File outputFile = new File(destFile);
			if (!outputFile.getParentFile().exists()) {
				outputFile.getParentFile().mkdirs();
			}
			String officeHome = getOfficeHome();

			DefaultOfficeManagerBuilder config = new DefaultOfficeManagerBuilder();

			config.setOfficeHome(officeHome);
			config.setPortNumber(Integer.parseInt(AppUtil.getProperty("office.port", "2002")));

			officeManager = config.build();
			officeManager.start();

			OfficeDocumentConverter converter = new OfficeDocumentConverter(officeManager);

			converter.convert(inputFile, outputFile);
			officeManager.stop();

			return 0;
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (officeManager != null) {
				try {
					officeManager.stop();
				} catch (OfficeException e) {
					e.printStackTrace();
				}
			}
		}

		return 1;
	}

	private static String getOfficeHome() {
		String OFFICE_HOME = AppUtil.getProperty("office.home");// 这里是OpenOffice的安装目录
		// 如果从文件中读取的URL地址最后一个字符不是 '\'，则添加'\'
		if (OFFICE_HOME.charAt(OFFICE_HOME.length() - 1) != File.separatorChar) {
			OFFICE_HOME += File.separatorChar;
		}
		return OFFICE_HOME;
	}

}
